#include "../include/ByteString.h"
#include "../include/global.h"
#include "../include/Tool.h"

namespace ZY {

    ByteString::~ByteString()
    {
        //dtor

    }

    uint64_t ByteString::getUnsignedInt64()
    {
        uint64_t n;
        m_str.copy( (char*) & n , sizeof( uint64_t ) , read_offset );
        read_offset += sizeof( uint64_t ) ;
        return Tool::ntohl64( n );
    }

    int64_t ByteString::getInt64()
    {
        return (int64_t ) getUnsignedInt64();
    }

    uint32_t ByteString::getUnsignedInt32()
    {
        uint32_t n;
        m_str.copy( (char*) & n , sizeof( uint32_t ) , read_offset );
        read_offset += sizeof( uint32_t ) ;
        return ntohl( n );
    }

    int32_t ByteString::getInt32()
    {
        return (int32_t) getUnsignedInt32();
    }

    uint16_t ByteString::getUnsignedInt16()
    {
        uint16_t n;
        m_str.copy( (char*) & n , sizeof( uint16_t ) , read_offset );
        read_offset += sizeof( uint16_t ) ;
        return ntohs( n );
    }

    int16_t ByteString::getInt16()
    {
        return (int16_t) getUnsignedInt16();
    }

    uint8_t ByteString::getUnsignedInt8()
    {
        uint8_t n;
        m_str.copy( (char*) & n , sizeof( uint8_t ) , read_offset );
        read_offset += sizeof( uint8_t ) ;
        return n;
    }

    int8_t ByteString::getInt8()
    {
        return (int8_t) getUnsignedInt8();
    }

    ByteString * ByteString::getCharArray( char *c , size_t size )
    {
        if ( size > 0 ) {
            m_str.copy( c , size , read_offset );
            read_offset += size;
        }
        return this;
    }

    ByteString * ByteString::getString( string &str , size_t size )
    {
        if ( size > 0 ) {
            char buff[size];
            getCharArray( buff , size );
            str.assign( buff , size );
        }
        return this;
    }

    ByteString * ByteString::getVarCharArray( char *c , size_t & size )
    {
        uint16_t len;
        len = getUnsignedInt16();
        getCharArray( c , len );
        size = len;
        return this;
    }

    ByteString * ByteString::getVarString( string & str )
    {
        uint16_t len;
        len = getUnsignedInt16();
        char c[len];
        getCharArray( c , len );
        string t_str( c , len );
        str.swap( t_str );
        return this;
    }

    ByteString * ByteString::setUnsignedInt64( uint64_t n )
    {
        uint64_t n1;
        char *c;
        n1 = Tool::htonl64( n );
        c = (char*) & n1;
        m_str.append( c , sizeof( uint64_t ) );
        write_offset += sizeof( uint64_t );
        return this;
    }
    ByteString * ByteString::setInt64( int64_t n )
    {
        return setUnsignedInt64( (uint64_t) n );
    }

    ByteString * ByteString::setUnsignedInt32( uint32_t n )
    {
        uint32_t n1;
        char *c;
        n1 = htonl( n );
        c = (char*) & n1;
        m_str.append( c , sizeof( uint32_t ) );
        write_offset += sizeof( uint32_t );
        return this;
    }
    ByteString * ByteString::setInt32( int32_t n )
    {
        return setUnsignedInt32( (uint32_t) n );
    }

    ByteString * ByteString::setUnsignedInt16( uint16_t n )
    {
        uint16_t n1;
        char *c;
        n1 = htons( n );
        c = (char*) & n1;
        m_str.append( c , sizeof( uint16_t ) );
        write_offset += sizeof( uint16_t );
        return this;
    }
    ByteString * ByteString::setInt16( int16_t n )
    {
        return setUnsignedInt16( (uint16_t) n );
    }

    ByteString * ByteString::setUnsignedInt8( uint8_t n )
    {
        char *c;
        c = (char*) & n;
        m_str.append( c , sizeof( uint8_t ) );
        write_offset += sizeof( uint8_t );
        return this;
    }
    ByteString * ByteString::setInt8( int8_t n )
    {
        return setUnsignedInt8( (uint8_t) n );
    }

    ByteString * ByteString::setCharArray( const char *c , size_t size )
    {
        m_str.append( c , size );
        write_offset += size;
        return this;
    }

    ByteString * ByteString::setString( const  string & str )
    {
        m_str.append( str );
        write_offset += str.length();
        return this;
    }

    ByteString * ByteString::setVarCharArray( const char *c , size_t size )
    {
        return setUnsignedInt16( size )->setCharArray( c , size );
    }
    ByteString * ByteString::setVarString( const string & str )
    {
        return setUnsignedInt16( str.length() )->setString( str );
    }

    ByteString * ByteString::setByteString( ByteString & bs )
    {
        if ( bs.read_offset > 0 ) {
            //说明有空间可以压缩，压缩的目的是使拼接更简单
            bs.zip();
        }

        if ( bs.write_offset > 0 ) {
            //说明有数据需要复制
            m_str.append( bs.m_str );
            write_offset += bs.write_offset;
        }

        return this;
    }

    //数据压缩，只会保留read_offset与write_offset之间的数据
    void ByteString::zip()
    {
        int len;

        len = write_offset - read_offset;

        if ( len <= 0 ) {
            read_offset = write_offset = 0;
            m_str.assign("");
        } else {

            string t_str( m_str.data() + read_offset , len );

            m_str.swap( t_str );
            read_offset = 0;
            write_offset = len;
        }
    }

    void ByteString::swap( ByteString & bs )
    {
        uint32_t i;
        bs.m_str.swap( m_str );
        i = bs.read_offset;
        bs.read_offset = read_offset;
        read_offset = i;
        i = bs.write_offset;
        bs.write_offset = write_offset;
        write_offset = i;
    }

    void ByteString::copyFrom( ByteString &bs )
    {
        read_offset = bs.read_offset;
        write_offset = bs.write_offset;
        m_str.assign( bs.m_str );
    }

    void ByteString::copyTo( ByteString &bs )
    {
        bs.read_offset = read_offset;
        bs.write_offset = write_offset;
        bs.m_str.assign( m_str );
    }
}
